package com.yhj.servlet.container;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class HttpServletRequest implements ServletRequest {

	/**
	 * URL是Internet上用来描述信息资源的字符串，主要用在各种WWW客户程序和服务器程序上。采用URL可以用一种统一的格式来描述各种信息资源，包括文件、服务器的地址和目录等。
　　		URL的格式由下列三部分组成：
			协议（或称为服务方式）；
			存有该资源的主机IP地址（有时也包括端口号）；
			主机资源的具体地址。如目录和文件名等。
		URI是以某种统一的（标准化的）方式标识资源的简单字符串，
		一般由三部分组成：
			访问资源的命名机制。
			存放资源的主机名。
			资源自身的名称，由路径表示。
	 */
	private String uri;
	/**一个请求头示例
	 * POST /examples/default.jsp HTTP/1.1  
		Accept: text/plain; text/html  
		Accept-Language: en-gb  
		Connection: Keep-Alive  
		Host: localhost  
		User-Agent: Mozilla/4.0  
		Content-Length: 33  
		Content-Type: application/x-www-form-urlencoded  
		Accept-Encoding: gzip, deflate  
  
		lastName=Franks&firstName=Michael  
	 */
	private InputStream iis;
	
	private String method;
	
	private Map<String ,String>parameter=new Hashtable<String ,String>();//形成request.getParamter("key")的效果
	
	/**
	 * 构造方法，传入一个输入流
	 * @param uri
	 * @param iis
	 */
	public HttpServletRequest( InputStream iis) {
		super();
		this.iis = iis;
	}
	public HttpServletRequest() {
		super();
	}
	/**
	 * 解析协议:最重要的就是取出uri
	 */
	public void parse(){
		//从input中读出所有的内容(http请求协议=》protocal)
		String protocal=null;
		//TODO:从iis流中取出protocal
		StringBuffer sb=new StringBuffer(1024*10);//10k大小，一次性读取
		int length=-1;
		byte[] bs=new byte[1024*10];
		
		try {
			length=this.iis.read(bs);
		} catch (IOException e) {
			e.printStackTrace();
			//读取发生了错误
			length=-1;//如果发生解析错误，则处理protocal时将其赋值为null，则后续操作将无法执行，记住对于null的操作
		}
		for(int j=0;j<length;j++){
			sb.append((char)bs[j]);
			protocal=sb.toString();
		}
		//从protocal中取出uri
		if(protocal==null||"".equals(protocal)){
			return ;
		}
		this.uri=parseUri(protocal);//解析出uri
		
		this.method=parseMethod(protocal);//解析出method
		
		this.parameter=parseParameter(protocal);//解析出所有的参数
	}
	
	/**
	 * 解析参数
	 * @param protocal
	 * @return
	 */
	//  GET /servlet/hello?name=yhj&age=21 HTTP/1.1
		
	// POST /servlet/hello
		
	//		name=yhj&age=20
	private Map<String, String> parseParameter(String protocal) {
		String parameterString=null;
		//取出参数部分，存到parameterString中取
		if(this.method.equals(TomcatConstants.REQUEST_METHOD_GET)){//如果是Get方式，则paramter接在uri后面，从protocal中取出第一个空格到第二个空格之间的字符串
			String[] ss=protocal.split(" ");
			int questionindex=ss[1].indexOf("?");
			if(questionindex>0){
				//只要有？，就截取
				parameterString=ss[1].substring(questionindex+1);
			}
		}else if(this.method.equals(TomcatConstants.REQUEST_METHOD_POST)){//如果是Post方式，则在请求头的最后
			parameterString=protocal.substring(protocal.lastIndexOf("\n")+1);
		}
		String []  keyvalues=null;
		if(parameterString!=null&&parameterString.length()>0){
			keyvalues=parameterString.split("&");//取出所有的参数对
			for(int i=0;i<keyvalues.length;i++){
				String keyvalu=keyvalues[i];//取出每一对
				String [] kv=keyvalu.split("=");//键值分开
				this.parameter.put(kv[0], kv[1]);//存到map中，返回
			}
		}
		return parameter;
	}
	private String parseMethod(String protocal) {
		String method=protocal.substring(0, protocal.indexOf(" "));//请求头是固定的，由之前给出的示例可以看出method的位置
		return method;
	}
	public String parseProtocal(String iis){
		String protocal=null;
		return protocal;
	}
	
	public String parseUri(String protocal){
		//TODO:从protocal中解析出uri
		if(protocal==null||"".equals(protocal)){
			return null;//防止之前protocal为空，将不执行任何操作
		}
		String [] ss=protocal.split(" ");
		
		if(validateProtocal(ss)!=200){//校验的操作，这里不做实现，默认验证通过
			return null;
		}
		if(ss[1].indexOf("?")>0){
			this.uri=ss[1].substring(0,ss[1].indexOf("?"));//如果有参数，则先把参数去掉，
		}else{
			this.uri=ss[1];
		}
		return this.uri;
	}
	
	public int validateProtocal(String[] s){
		return 200;
	}
	
	public String getUri(){
		return uri;
	}
	@Override
	public String getMethod() {
		return this.method;
	}
	@Override
	public String getParameter(String key) {
		return this.parameter.get(key);
	}
	@Override
	public HashMap<String, String> getSession() {
		HashMap<String, String> temp=new HashMap<String,String>();
		//temp.get(key)
		return null;
	}
	
}
